﻿using System;
using System.Globalization;
using System.Collections;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Net.Http;
using System.IO;
using EventbriteService;
using EventbriteService.Model;
using Eventbrite.LinqProvider;
using EventbriteService.Factory;
using EventbriteService.Linq.Extensibility;
using EventbriteService.Adapter;

namespace LinqProviderSampleCode
{
    class Program
    {
        private const string dateFormate = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";
        private const string yourAppKey = "your app key";

        //************************ Linq provider calls samples**********************************

        static void OrderBy()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = (from e in client.Query
                      where (e.Request.DateCreated >= DateTime.Today.AddMonths(-4) &
                             e.Request.DateCreated < DateTime.Today.AddMonths(-3)) &
                             e.Request.Country == "US" &
                             e.Request.Region == "IN" &
                             e.Request.Categories == Categories.Business
                      orderby e.Request.Date
                      select new
                      {
                          Id = e.Id,
                          City = e.Venue.Address.City,
                          Name = e.Organizer.Name,
                          Dates = e.Start.DisplayLocal()
                      }
                          ).ToArray();

        }

        static void Projection()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = (from e in client.Query
                      where (e.Request.DateCreated >= DateTime.Today.AddMonths(-4) &
                             e.Request.DateCreated < DateTime.Today.AddMonths(-3)) &
                             e.Request.Country == "US" &
                             e.Request.City == "Indianapolis" &
                             e.Request.Region == "IN" &
                             e.Request.Categories == Categories.Business
                      select new OrganizerInfo
                      {
                          Id = e.Organizer.Id.Value,
                          Name = e.Organizer.Name,
                          Dates = e.Start.DisplayLocal()
                      }
                          ).ToArray();

        }

        static void EnumsTest()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var q = (from e in client.Query
                     where e.Request.Categories == (Categories.Music | Categories.Government) &
                     e.Request.Formats == (Formats.Class | Formats.Game)
                     select e).ToArray();

            foreach (var @event in q)
            {
                if (@event.Category.ShortName != "Music" && @event.Category.ShortName != "Government")

                    throw new ApplicationException("wrong results");
            }

        }

        static void SearchKeywords()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var q = (from e in client.Query
                     where e.Request.Country == "US" & e.Request.Region == "IN"
                     select e).SearchKeywords("yoga", "bike").ToArray();
            foreach (var @event in q)
            {
                if (@event.Description.Text == null || @event.Name.Text == null)
                    continue;
                if ((!@event.Description.Text.ToLower().Contains("bike") && !@event.Description.Text.ToLower().Contains("yoga")) &&
                    (!@event.Name.Text.ToLower().Contains("bike") && !@event.Name.Text.ToLower().Contains("yoga"))
                    )
                    throw new ApplicationException("wrong results");
            }
        }

        static void LongitudeLatitude()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = from e in client.Query
                     // internally linq provider converts local date to utc
                     where
                           e.Request.Latitude == "40.764469" &
                           e.Request.Longitude == "-73.97448800000001" &
                           e.Request.Within == "1km"

                     select e;
            foreach (var @event in qq)
            {

                if (@event.Venue.Address.Region.Trim() != "NY" && @event.Venue.Address.Region.Trim() != "USA" && @event.Venue.Address.Region.Trim() != "New York")
                    throw new ApplicationException("incorrect result");
            }
        }

        static void DateRange()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = from e in client.Query
                     where
                           e.Request.Date > DateTime.Today.AddDays(-10) &
                           e.Request.Date < DateTime.Today.AddDays(-5) &
                           e.Request.Categories == Categories.Arts
                     select e;
            foreach (var @event in qq)
            {


                //Only return events with start dates before the given date.
                if (DateTime.ParseExact(@event.Start.Utc, dateFormate, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).Date < DateTime.UtcNow.AddDays(-10).Date &&
                    DateTime.ParseExact(@event.End.Utc, dateFormate, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).Date > DateTime.UtcNow.AddDays(-5).Date)
                    throw new ApplicationException("incorrect result");
            }
        }

        static void DateRangeBeforeTheGivenDate()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = from e in client.Query
                     // internally linq provider converts local date to utc
                     where e.Request.Date < DateTime.Today.AddDays(-5) &

                     e.Request.Categories == Categories.Arts
                     select e;

            foreach (var @event in qq)
            {

                //Only return events with start dates before the given date.
                if (DateTime.ParseExact(@event.Start.Utc, dateFormate, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).Date > DateTime.UtcNow.AddDays(-5).Date)
                    throw new ApplicationException("incorrect result");
            }

        }
        static void DateRangeAfterTheGivenDate()
        {

            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = from e in client.Query
                     // internally linq provider converts local date to utc
                     where e.Request.Date == DateTime.Today.AddDays(-5) &

                     e.Request.Categories == Categories.Arts
                     select e;

            foreach (var @event in qq)
            {

                //Only return events with start dates after the given date.
                if (DateTime.ParseExact(@event.Start.Utc, dateFormate, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).Date < DateTime.UtcNow.AddDays(-5).Date)
                    throw new ApplicationException("incorrect result");
            }

        }

        static void FilterWithDateRange()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var qq = from e in client.Query
                     where e.Request.Categories == Categories.Arts &
                        (e.Request.DateCreated >= DateTime.Today.AddYears(-1) &
                         e.Request.DateCreated < DateTime.Today.AddDays(-30)) &
                        (e.Request.DateModified > DateTime.Today.AddMonths(-5) &
                         e.Request.DateModified < DateTime.Today.AddMonths(-1))
                     select e;
            foreach (var @event in qq)
            {
                if ((@event.Created.Value.Date < DateTime.Today.AddYears(-1) ||
                    @event.Created.Value.Date > DateTime.Today.AddDays(-30)) &&
                    (@event.Changed.Value.Date < DateTime.Today.AddMonths(-5)) ||
                    (@event.Changed.Value.Date > DateTime.Today.AddMonths(-1)))
                    throw new ApplicationException("incorrect result");
            }

        }

        static void FilterWithDate_ThisWeek()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e => e.Request.DateCreatedKeyword == DateKeywords.ThisWeek &
                                                  e.Request.Categories == Categories.Arts);
            foreach (var @event in events)
            {
                if (@event.Created.Value.Date < DateTime.Today.AddDays(-7) || @event.Created.Value.Date > DateTime.Today)
                    throw new ApplicationException("incorrect result");
            }
        }

        static void FilterWithDate_Today()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e => e.Request.DateCreatedKeyword == DateKeywords.Today &
                                                  e.Request.Categories == Categories.Arts);
            foreach (var @event in events)
            {
                if (@event.Created.Value.Date != DateTime.Today)
                    throw new ApplicationException("incorrect result");
            }
        }

        static void FilterWithCategories()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e => e.Request.DateCreatedKeyword == DateKeywords.Today &
                                                   e.Request.Categories == Categories.Arts);
            foreach (var @event in events)
            {
                if (@event.Category.ShortName != "Arts")
                    throw new ApplicationException("incorrect result");
            }

        }

        static void FilterWithUser()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e => e.Request.User == 65038969027);
            foreach (var @event in events)
            {

            }
        }
        static void FilterWithOrganizer()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e => e.Request.Organizer == 2527952660);
            foreach (var @event in events)
            {
                if (@event.OrganizerId != 2527952660)
                    throw new ApplicationException("wrong result");
            }
        }
        static void FilterWithAddress()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e =>
                                                   e.Request.Country == "US" &
                                                   e.Request.Region == "NY" &
                                                   e.Request.City == "New York" &
                                                   e.Request.Address == "695 Park Avenue" &
                                                   e.Request.Within == "1km"
                                                   );
            foreach (var @event in events)
            {
                if (!@event.Venue.Address.City.StartsWith("New York"))
                    throw new ApplicationException("incorrect result");
            }

        }
        static void FilterWithLocation()
        {
            EventbriteContext context = new EventbriteContext(yourAppKey);
            var events = context.Query.Where(e =>
                                                   e.Request.DateCreatedKeyword == DateKeywords.Today &
                                                   e.Request.Country == "US" &
                                                   e.Request.Region == "NY" &
                                                   e.Request.City == "New York"
                                                   );
            foreach (var @event in events)
            {
                if (@event.Venue.Address.Region != "NY")
                    throw new ApplicationException("incorrect result");
            }

        }

        //************************ API Calls Samples ********************************************

        static void GetUserEvents()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetUserEvents();

        }

        static void GetVenue()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetVenue(10422930);

        }

        static void GetUserVenues()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetUserVenues();

        }

        static void GetUserOrganizer()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetUserOrganizers();

        }

        static void GetUser()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetUser();

        }

        static void GetEventAttendees()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.EventAttendees(3798681960);

        }

        static void GetEvent()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetEvent(16332069660);

        }
        static void GetEventOrders()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var f = client.Client.GetEventOrders(10583189605).ToArray();

        }

        static void GetUserOrder()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetUserOrders(null);

        }

        static void GetOrder()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var e = client.Client.GetOrder(252403251);

        }

        static void GetFormates()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var formates = client.Client.GetFormats();
        }

        static void GetCategories()
        {
            EventbriteContext client = new EventbriteContext(yourAppKey);
            var formates = client.Client.GetCategories();
        }

        static void Main(string[] args)
        {
            OrderBy();
            Projection();
            EnumsTest();
            SearchKeywords();
            LongitudeLatitude();
            FilterWithAddress();

            DateRange();
            DateRangeBeforeTheGivenDate();
            DateRangeAfterTheGivenDate();
            FilterWithDateRange();
            FilterWithDate_ThisWeek();

            FilterWithDate_Today();

            FilterWithLocation();
            FilterWithUser();
            FilterWithOrganizer();
            FilterWithCategories();

        }
    }

    public class OrganizerInfo
    {
        public string Name { get; set; }
        public long Id { get; set; }
        public object Dates { get; set; }
        public int TicketNumber { get; set; }
    }

    class HttpWebClient : IClientSource
    {

        #region IClientSource Members

        public string Read(Uri requestUrl)
        {
            using (HttpClient client = new HttpClient())
            using (StreamReader reader = new StreamReader(client.GetStreamAsync(requestUrl).Result))
                return reader.ReadToEnd();
        }

        #endregion
    }
}
